package com.anti.modular.sys.role.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.anti.commom.constant.CommonConstant;
import com.anti.commom.core.exception.BusinessException;
import com.anti.commom.core.exception.enums.PermissionExceptionEnum;
import com.anti.commom.enums.CommonStatusEnum;
import com.anti.core.context.login.LoginContextHolder;
import com.anti.core.enums.DataScopeTypeEnum;
import com.anti.jdbc.DBUtils;
import com.anti.jdbc.support.page.PageParam;
import com.anti.jdbc.support.page.PageResult;
import com.anti.modular.sys.org.service.SysOrgService;
import com.anti.modular.sys.role.dao.SysRoleDao;
import com.anti.modular.sys.role.entity.SysRole;
import com.anti.modular.sys.role.param.SysRoleParam;
import com.anti.modular.sys.role.service.SysRoleDataScopeService;
import com.anti.modular.sys.role.service.SysRoleMenuService;
import com.anti.modular.sys.role.service.SysRoleService;
import io.swagger.models.auth.In;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Description TODO
 * @Author anTi
 * @Date 2021-2-26
 */
@Service
public class SysRoleServiceImpl implements SysRoleService {
    @Resource
    DBUtils dbUtils;
    @Resource
    SysRoleMenuService sysRoleMenuService;
    @Resource
    SysRoleDataScopeService sysRoleDataScopeService;
    @Resource
    SysRoleDao sysRoleDao;

    @Resource
    SysOrgService sysOrgService;

    @Override
    public void add(SysRoleParam sysRoleParam) {
        checkParam(sysRoleParam, false);
        SysRole sysRole = new SysRole();
        BeanUtil.copyProperties(sysRoleParam, sysRole);
        sysRole.setStatus(CommonStatusEnum.ENABLE.getCode());
        sysRole.setCreateTime(new Date());
        sysRole.setCreateUser(LoginContextHolder.me().getSysLoginUserId());
        sysRoleDao.save(sysRole);
    }

    @Override
    public void delete(SysRoleParam sysRoleParam) {
        sysRoleDao.delete(sysRoleParam.getId());
    }

    @Override
    public void edit(SysRoleParam sysRoleParam) {
        checkParam(sysRoleParam, true);
        SysRole sysRole = new SysRole();
        BeanUtil.copyProperties(sysRoleParam, sysRole);
        sysRole.setUpdateTime(new Date());
        sysRole.setUpdateUser(LoginContextHolder.me().getSysLoginUserId());
        sysRoleDao.edit(sysRole);
    }

    @Override
    public List<Dict> getLoginRoles(Long userId) {
        List<Dict> dictList = CollectionUtil.newArrayList();
        //获取用户角色id集合
        String sql="select * from sys_role  where status=0 and id in (select role_id from sys_user_role where user_id=?)";
        List<SysRole> query = dbUtils.query(sql, SysRole.class, userId);
        query.forEach(sysRole -> {
            Dict dict = Dict.create();
            dict.put(CommonConstant.ID, sysRole.getId());
            dict.put(CommonConstant.CODE, sysRole.getCode());
            dict.put(CommonConstant.NAME, sysRole.getName());
            dictList.add(dict);
        });
        return dictList;
    }

    @Override
    public PageResult page(PageParam pageParam, SysRoleParam sysRoleParam) {
        StringBuilder sb=new StringBuilder("select * from sys_role where status=0 ");
        Map<String,String> params=new HashMap<>();
        if (ObjectUtil.isNotNull(sysRoleParam)) {
            //根据名称模糊查询
            if (ObjectUtil.isNotEmpty(sysRoleParam.getName())) {
                sb.append(" and name like :name ");
                params.put("name","%"+sysRoleParam.getName()+"%");
            }
            //根据编码模糊查询
            if (ObjectUtil.isNotEmpty(sysRoleParam.getCode())) {
                sb.append(" and code like :code ");
                params.put("code","%"+sysRoleParam.getCode()+"%");
            }
        }
        sb.append("  order by sort asc ");
        PageResult pageResult = dbUtils.query(pageParam, sb.toString(), params);
        return pageResult;
    }


    @Override
    public List<Long> ownMenu(SysRoleParam sysRoleParam) {
        SysRole sysRole = this.querySysRole(sysRoleParam);
        return sysRoleMenuService.getRoleMenuIdList(CollectionUtil.newArrayList(sysRole.getId()));
    }


    @Override
    public void saveGrantMenu(SysRoleParam sysRoleParam) {
        this.querySysRole(sysRoleParam);
        sysRoleMenuService.saveGrantMenu(sysRoleParam);
    }

    @Override
    public void saveGrantData(SysRoleParam sysRoleParam) {
        SysRole sysRole = this.querySysRole(sysRoleParam);
        boolean superAdmin = LoginContextHolder.me().isSuperAdmin();
        //如果登录用户不是超级管理员，则进行数据权限校验
        if (!superAdmin) {
            Integer dataScopeType = sysRoleParam.getDataScopeType();
            //如果授权的角色的数据范围类型为全部，则没权限，只有超级管理员有
            if (DataScopeTypeEnum.ALL.getCode().equals(dataScopeType)) {
                throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
            }
            //如果授权的角色数据范围类型为自定义，则要判断授权的数据范围是否在自己的数据范围内
            if (DataScopeTypeEnum.DEFINE.getCode().equals(dataScopeType)) {
                List<Long> dataScope = sysRoleParam.getDataScope();
                //要授权的数据范围列表
                List<Long> grantOrgIdList = sysRoleParam.getGrantOrgIdList();
                if (ObjectUtil.isNotEmpty(grantOrgIdList)) {
                    //数据范围为空
                    if (ObjectUtil.isEmpty(dataScope)) {
                        throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
                    } else if (!dataScope.containsAll(grantOrgIdList)) {
                        //所要授权的数据不在自己的数据范围内
                        throw new BusinessException(PermissionExceptionEnum.NO_PERMISSION_OPERATE);
                    }
                }
            }
        }
        sysRole.setDataScopeType(sysRoleParam.getDataScopeType());
        sysRoleDao.edit(sysRole);
        sysRoleDataScopeService.saveGrantDataScope(sysRoleParam);
    }

    @Override
    public List<Long> ownData(SysRoleParam sysRoleParam) {
        SysRole sysRole = this.querySysRole(sysRoleParam);
        return sysRoleDataScopeService.getRoleDataScopeIdList(CollectionUtil.newArrayList(sysRole.getId()));
    }

    @Override
    public List<Long> getUserDataScopeIdList(List<Long> roleIdList, Long orgId) {
        Set<Long> resultList = CollectionUtil.newHashSet();

        //定义角色中最大数据范围的类型，目前系统按最大范围策略来，如果你同时拥有ALL和SELF的权限，系统最后按ALL返回
        Integer strongerDataScopeType = DataScopeTypeEnum.SELF.getCode();

        //获取用户自定义数据范围的角色集合
        List<Long> customDataScopeRoleIdList = CollectionUtil.newArrayList();
        if (ObjectUtil.isNotEmpty(roleIdList)) {
            String sql="select * from sys_role where id in (:ids)";
            HashMap<Object, Object> param = CollectionUtil.newHashMap();
            param.put("ids",roleIdList);
            List<SysRole> sysRoleList = dbUtils.query(sql,SysRole.class,param);
            for (SysRole sysRole : sysRoleList) {
                if (DataScopeTypeEnum.DEFINE.getCode().equals(sysRole.getDataScopeType())) {
                    customDataScopeRoleIdList.add(sysRole.getId());
                } else {
                    if (sysRole.getDataScopeType() <= strongerDataScopeType) {
                        strongerDataScopeType = sysRole.getDataScopeType();
                    }
                }
            }
        }
        //角色中拥有最大数据范围类型的数据范围
        List<Long> dataScopeIdList = sysOrgService.getDataScopeListByDataScopeType(strongerDataScopeType, orgId);
        resultList.addAll(dataScopeIdList);
        //自定义数据范围的角色对应的数据范围
        if (customDataScopeRoleIdList.size()>0){
            List<Long> roleDataScopeIdList = sysRoleDataScopeService.getRoleDataScopeIdList(customDataScopeRoleIdList);
            resultList.addAll(roleDataScopeIdList);
        }
        return CollectionUtil.newArrayList(resultList);
    }

    private void checkParam(SysRoleParam sysRoleParam, boolean b) {
        Long id = sysRoleParam.getId();
        String name = sysRoleParam.getName();
        String code = sysRoleParam.getCode();
        List params=new ArrayList();
        StringBuilder sb=new StringBuilder("select count(*) from sys_role where status=0 and name=? and code=? ");
        params.add(name);
        params.add(code);
        //是否排除自己，如果排除自己则不查询自己的id
        if (b) {
            sb.append(" and id <> ?");
            params.add(id);
        }
        int countByName = dbUtils.getFirst(sb.toString(), Integer.class,params.toArray());
        if (countByName >= 1) {
            throw new BusinessException(0,"");
        }
    }

    /**
     * 获取系统角色
     *
     * @author xuyuxiang
     * @date 2020/3/28 14:59
     */
    private SysRole querySysRole(SysRoleParam sysRoleParam) {
        SysRole sysRole = dbUtils.getFirst("SELECT * FROM sys_role WHERE ID=?",SysRole.class,sysRoleParam.getId());
        if (ObjectUtil.isNull(sysRole)) {
            throw new BusinessException(0,"角色不存在！");
        }
        return sysRole;
    }

}
